﻿using System;
using Autodesk.Revit.DB;
using YJKRevitKernel.TransactionUtility;
using YJKRevitKernel.XYZUtility;

namespace YJKRevitKernel.ElementEditUtility.TextNoteEditUtility
{
	public static class TextNoteRoateUtility
	{
		public static bool TryRoateTextNote(TextNote inputTextNote, double dInputAngle, bool ifUseSubTransaction = false, bool ifAlinBottomPostion = true)
		{
			TextNoteRoateContext textNoteRoateContext = new TextNoteRoateContext();
			textNoteRoateContext.ThisTextNote = inputTextNote;
			textNoteRoateContext.UseRoateValue = dInputAngle;
			textNoteRoateContext.IfAlignAtBottom = ifAlinBottomPostion;
			TransactionWorkDelegate useDelegate = new TransactionWorkDelegate(TextNoteRoateUtility.RoateTextNote);
			Exception ex = null;
			return RevitTransactionManger.DoTransaction(inputTextNote.Document, useDelegate, textNoteRoateContext, out ex, ifUseSubTransaction, null);
		}

		private static bool RoateTextNote(object inputContext)
		{
			return TextNoteRoateUtility.RoateTextNote(inputContext as TextNoteRoateContext);
		}

		private static bool RoateTextNote(TextNoteRoateContext inputContext)
		{
			TextNoteRoateUtility.RoateTextNote(inputContext.ThisTextNote, inputContext.UseRoateValue, inputContext.IfAlignAtBottom);
			return true;
		}

		private static void RoateTextNote(TextNote inputTextNote, double dInputAngle, bool ifAlinBottomPostion)
		{
			Document document = inputTextNote.Document;
			double tempWidth;
			double tempHight;
			XYZ tempCoord;
			TextNoteRoateUtility.CalculateCoordPoint(inputTextNote, out tempWidth, out tempHight, out tempCoord);
			XYZ xyz;
			XYZ inputPoint;
			TextNoteRoateUtility.CalculateTopAndBottomMidPoint(inputTextNote, out xyz, out inputPoint);
			TextNoteRoateUtility.RoateTextNotByMidAxis(inputTextNote, dInputAngle, document, tempWidth, tempHight, tempCoord);
			if (!ifAlinBottomPostion)
			{
				return;
			}
			document.Regenerate();
			TextNoteRoateUtility.AlignTextNoteAtBottomMidPoint(inputTextNote, document, inputPoint);
		}

		private static void AlignTextNoteAtBottomMidPoint(TextNote inputTextNote, Autodesk.Revit.DB.Document tempDoc, XYZ inputPoint)
		{
			inputTextNote = (tempDoc.GetElement(inputTextNote.Id) as TextNote);
			XYZ xyz;
			XYZ xyz2;
			TextNoteRoateUtility.CalculateTopAndBottomMidPoint(inputTextNote, out xyz, out xyz2);
			XYZ xyz3 = (inputPoint.DistanceTo(xyz2) > inputPoint.DistanceTo(xyz)) ? xyz : xyz2;
			XYZ xyz4 = inputPoint - xyz3;
			ElementTransformUtils.MoveElement(tempDoc, inputTextNote.Id, xyz4);
		}

		private static void CalculateTopAndBottomMidPoint(TextNote inputTextNote, out XYZ topMidPoint, out XYZ bottomMidPoint)
		{
			topMidPoint = null;
			bottomMidPoint = null;
			double num;
			double num2;
			XYZ xyz;
			TextNoteRoateUtility.CalculateCoordPoint(inputTextNote, out num, out num2, out xyz);
			topMidPoint = xyz + inputTextNote.BaseDirection.Multiply(0.5 * num);
			bottomMidPoint = topMidPoint - inputTextNote.UpDirection.Multiply(num2);
		}

		private static void RoateTextNotByMidAxis(TextNote inputTextNote, double dInputAngle, Autodesk.Revit.DB.Document tempDoc, double tempWidth, double tempHight, XYZ tempCoord)
		{
			Autodesk.Revit.DB.View view = tempDoc.GetElement(inputTextNote.OwnerViewId) as Autodesk.Revit.DB.View;
			BoundingBoxXYZ boundingBoxXYZ = new BoundingBoxXYZ();
			boundingBoxXYZ.Max = tempCoord;
			boundingBoxXYZ.Min = tempCoord + inputTextNote.BaseDirection.Multiply(tempWidth) - inputTextNote.UpDirection.Multiply(tempHight);
			Line line = Line.CreateUnbound(XYZUtilityMethod.CalculatMidPoint(boundingBoxXYZ.Max, boundingBoxXYZ.Min), view.ViewDirection);
			ElementTransformUtils.RotateElement(tempDoc, inputTextNote.Id, line, dInputAngle);
		}

		private static void CalculateCoordPoint(TextNote inputTextNote, out double tempWidth, out double tempHight, out XYZ tempCoord)
		{
			Autodesk.Revit.DB.View view = inputTextNote.Document.GetElement(inputTextNote.OwnerViewId) as Autodesk.Revit.DB.View;
			tempWidth = inputTextNote.Width * (double)view.Scale;
			tempHight = inputTextNote.Height * (double)view.Scale;
			tempCoord = inputTextNote.Coord;
			Transform transform = TextNoteRoateUtility.CalculateCoordTransform(inputTextNote, tempWidth, inputTextNote.BaseDirection);
			if (transform != null)
			{
				tempCoord = XYZUtilityMethod.TransformPoint(tempCoord, transform);
			}
		}

		private static Transform CalculateCoordTransform(TextNote inputTextNote, double tempWidth, XYZ tempDriection)
		{
			Transform result = null;
            switch ((int)inputTextNote.HorizontalAlignment)
			{
			case 1:
				result = Transform.CreateTranslation(tempDriection.Multiply(-tempWidth));
				break;
			case 2:
				result = Transform.CreateTranslation(tempDriection.Multiply(-0.5 * tempWidth));
				break;
			}
			return result;
		}
	}
}
